package android.project;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

public class AndroidProjectFinderActivity extends Activity implements OnClickListener 
{
	public static final String FOLDER_NAME = "/androidProjectDir";
	
	// Fields
	private Button m_findButton;
	private EditText m_editText;
	private ImageView m_imageView;
	private String m_inputText;
	private boolean m_foundPicture;
	private Bitmap m_bitmap;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle a_savedInstanceState) 
	{
	    super.onCreate(a_savedInstanceState);
	    
	    // See if any image was saved if so set the correct contentView and draw the image again.
	    m_bitmap = (Bitmap)getLastNonConfigurationInstance();
	    if (m_bitmap != null)
	    {
	    	setContentView(R.layout.finder_image);
	    	m_imageView = (ImageView)findViewById(R.id.finder_imageView_image);
	    	m_imageView.setImageBitmap(m_bitmap);
	    }
	    else
	    {
		    InitiateViews();
	    }
	}
	
	private void InitiateViews()
	{
	    setContentView(R.layout.finder_search);
	    
	    m_findButton = (Button)findViewById(R.id.finder_button_find);
	    m_editText = (EditText)findViewById(R.id.finder_editText_address);
	    m_imageView = (ImageView)findViewById(R.id.finder_imageView_image);
	    
	    m_findButton.setOnClickListener(this);
	    
	    m_foundPicture = false;
	    m_bitmap = null;
	}

	public void onClick(View a_v) 
	{
		// User clicked the button to find the picture on the given URL.
		if (a_v.getId() == R.id.finder_button_find)
		{
			m_inputText = m_editText.getText().toString();
			
			if (isInputValid() == true)
			{
				Log.d("debug-event", "URL was NOT null, start AsyncTask.");
				new DownloadImageTask().execute(m_inputText);

				
			}
			else
			{
				Toast.makeText(this, "Invalid URL!", Toast.LENGTH_SHORT).show();
				Log.d("debug-event", "URL was null.");
			}
		}
	}
	
	private boolean isInputValid()
	{
		URL url = null;
		
		// Check if the string contains the protocol (http://), otherwise try to add it then...
		if (m_inputText.startsWith("http://") == false)
		{
			// Check so the URL is not using HTTPS.
			if (m_inputText.startsWith("https://") == false)
			{
				m_inputText = "http://" + m_inputText;
			}
		}
		// If the user didn't write the protocol and it was supposed to be HTTPS and not HTTP and the URL passes
		// the malformedURL check then it will probably fail to find the file later on and we can give a file not
		// found error.
		
		// Check if the input contained a valid URL.
		try 
		{
			url = new URL(m_inputText);
		} 
		catch (MalformedURLException e) 
		{
			Log.d("debug-event", "Error: " + e.toString());
			e.printStackTrace();
		}
		
		// If the URL actually contains an address then return true otherwise return false.
		if (url != null)
		{
			return true;
		}
		return false;
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu a_menu) 
	{
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.menu_finder, a_menu);
		return true;
	}
	
	@Override
	public boolean onOptionsItemSelected(MenuItem a_item) 
	{		
		switch(a_item.getItemId())
		{
			case R.id.finder_item_save :
				if (m_foundPicture == false)
				{
					Log.d("debug-event", "No picture loaded therefore there's nothing to save.");
					Toast.makeText(this, "Error: No picture was loaded.", Toast.LENGTH_SHORT).show();
				}
				else
				{
					Log.d("debug-event", "A Picture was loaded, start AsyncTask.");
					new SaveImageTask().execute();
				}
				break;
			case R.id.finder_item_newSearch :
				if (m_foundPicture == true)
				{
					Log.d("debug-event", "Set ImageView to null and create the views again.");
					m_imageView.setImageBitmap(null);
					m_imageView = null;
					InitiateViews();
				}
				else
				{
					Log.d("debug-event", "Already showing the searchField hence nothing needs to be done.");
				}
				break;
		}
		return true;
	}
	
	@Override
	public Object onRetainNonConfigurationInstance() 
	{
		Bitmap data = m_bitmap;
		return data;
	}
	
	private class SaveImageTask extends AsyncTask<Void, Void, Boolean>
	{
		@Override
		protected Boolean doInBackground(Void... params) 
		{
			boolean ret = false;
			
			// Check if the necessary folder exists on the SD-card otherwise create it.
			File folder = new File(Environment.getExternalStorageDirectory() + FOLDER_NAME);
			if (folder.isDirectory() == false)
			{
				Log.d("debug-event", "Folder doesn't exists, try to create it.");
				if (folder.isFile() == false)
				{
					boolean temp = folder.mkdir();
					if (temp == false)
					{
						Log.d("debug-event", "Folder couldn't be created.");
					}
					else
					{
						Log.d("debug-event", "Folder was created successfully.");
					}
				}
			}
			else
			{
				Log.d("debug-event", "Folder already exists.");
			}
			
			if (m_bitmap != null)
			{				
				String fileName = getFileName();
				String filePath = "";
				
				// Get the path to the external storage.
				String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
				
				filePath = extStorageDirectory + FOLDER_NAME;
				
				Log.d("debug-event", "External filepath: " + filePath);
				
				// Create the outputstream.
				OutputStream outStream = null;
				
				// Create the file.
				File file = new File(filePath, fileName);
				
				try
				{
					// Set the outStream
					outStream = new FileOutputStream(file);
					
					// Compress the image.
					m_bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
					
					// Flush and then close the stream.
					outStream.flush();
					outStream.close();
				}
				catch(Exception e)
				{
					e.printStackTrace();
					Log.d("debug-event", "Error" + e.toString());
				}
				
				// Check if the file exists.
				if (file.exists() == true)
				{
					ret = true;
				}
			}
			return ret;
		}
		
		
		@Override
		protected void onPostExecute(Boolean result) 
		{
			Log.d("debug-event", "File exists: " + result);
			if (result == true)
			{
				Toast.makeText(getApplicationContext(), "Image was successfully saved!", Toast.LENGTH_SHORT).show();
			}

			super.onPostExecute(result);
		}
		
		private String getFileName()
		{
			String[] temp = m_inputText.split("/");
			int maxElement = temp.length - 1; // Minus one since arrays are 0 based.
			
			String name = temp[maxElement];
			
			Pattern p = Pattern.compile("[.]");
			
			// Split to see if the name contains a dot, this would mean that the string already contains a file ending.
			String[] newTemp = p.split(name);
			
			Log.d("debug-event", "NumberOfElementsInFileName: " + newTemp.length);
			
			// Check how many elements the name has.
			if (newTemp.length > 1)
			{
				// If it has more than one, delete the old file ending.
				name = newTemp[0];
			}
			
			// Add the file ending.
			name = name + ".png";
			
			Log.d("debug-event", "FileName: " + name);
			
			return name;
			
		}
	}
	
	private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>
	{
		@Override
		protected Bitmap doInBackground(String... a_params) 
		{
			return loadImageFromNetwork(a_params[0]);
		}
		
		@Override
		protected void onPostExecute(Bitmap a_result) 
		{
			if (a_result == null)
			{
				// No image was found, give errors.
				Log.d("debug-event", "No bitmap was returned from the given url.");
				Context context = getApplicationContext();
				Toast.makeText(context, "No image was found on the URL please\ncheck the spelling and make sure you've\nentered the correct address.", Toast.LENGTH_LONG).show();
			}
			else
			{
				// Image was found add i to the imageView and remove relevant controllers.
				Log.d("debug-event", "Image was found, adding it to the imageView.");
				
				setContentView(R.layout.finder_image);
				m_imageView = (ImageView)findViewById(R.id.finder_imageView_image);
				
				m_imageView.setImageBitmap(a_result);
				m_imageView.setVisibility(View.VISIBLE);
				m_foundPicture = true;
				m_bitmap = a_result;
				
			}
		}
		
		private Bitmap loadImageFromNetwork(String a_url)
		{
			// Try to download the image from the given URL and unless it throws exception return the bitmap.
			try
			{
				Bitmap bitmap = BitmapFactory.decodeStream((InputStream)new URL(a_url).getContent());
				return bitmap;
			}
			catch(Exception e)
			{
				Log.d("debug-event", "Error: " + e.toString());
				e.printStackTrace();
			}
			
			return null;
		}
	}
	
}